#pragma once

#include <windows.h>
#include <string>

namespace CaptureManager
{
	namespace COMServer
	{
		class RegisterManager
		{
		public:

			HRESULT registerServer(
				HINSTANCE aModuleInstance);

			HRESULT unregisterServer(
				HINSTANCE aModuleInstance);

		protected:
			RegisterManager(){};
			virtual ~RegisterManager(){};

		private:

			HRESULT getModuleFilePath(
				HINSTANCE aModuleInstance,
				LPWSTR lpFilename,
				DWORD nSize);

			HRESULT registerInprocServer(
				PCWSTR aFilePath,
				PCWSTR aFriendlyName,
				PCWSTR aThreadModel,
				PCWSTR aProgID,
				PCWSTR aVerIndProgID,
				REFCLSID aRefCLSID,
				REFIID aRefLibID);

			HRESULT unregisterInprocServer(
				PCWSTR aProgID,
				PCWSTR aVerIndProgID,
				REFCLSID aRefCLSID);

			HRESULT setRegistryKeyAndValue(
				PCWSTR aSubkeyString,
				PCWSTR aData,
				PCWSTR aName = nullptr);

			HRESULT registerTypeLib(
				PCWSTR aFilePath);

			HRESULT unregisterTypeLib(
				PCWSTR aFilePath);
		};
	}
}

//
//   FUNCTION: RegisterInprocServer
//
//   PURPOSE: Register the in-process component in the registry.
//
//   PARAMETERS:
//   * pszModule - Path of the module that contains the component
//   * clsid - Class ID of the component
//   * pszFriendlyName - Friendly name
//   * pszThreadModel - Threading model
//   * libid - Type library ID.
//   * pszProgID - ProgID of the component
//   * pszVerIndProgID - Version independent ProgID
//
//   NOTE: The function creates the HKCR\CLSID\{<CLSID>} key and the 
//   HKCR\<ProgID> key in the registry.
// 
//   HKCR
//   {
//      <ProgID> = s '<Friendly Name>'
//      {
//          CLSID = s '{<CLSID>}'
//      }
//      <VersionIndependentProgID> = s '<Friendly Name>'
//      {
//          CLSID = s '{<CLSID>}'
//          CurVer = s '<ProgID>'
//      }
//      NoRemove CLSID
//      {
//          ForceRemove {<CLSID>} = s '<Friendly Name>'
//          {
//              ProgID = s '<ProgID>'
//              VersionIndependentProgID = s '<VersionIndependentProgID>'
//              InprocServer32 = s '%MODULE%'
//              {
//                  val ThreadingModel = s '<Thread Model>'
//              }
//              TypeLib = s '{<LIBID>}'
//          }
//      }
//   }
//
HRESULT RegisterInprocServer(PCWSTR pszModule, 
                             const CLSID& clsid, 
                             PCWSTR pszFriendlyName,
                             PCWSTR pszThreadModel,
                             const IID& libid,
                             PCWSTR pszProgID, 
                             PCWSTR pszVerIndProgID);


//
//   FUNCTION: UnregisterInprocServer(void)
//
//   PURPOSE: Unegister the in-process component in the registry.
//
//   PARAMETERS:
//   * clsid - Class ID of the component
//   * pszProgID - ProgID of the component
//   * pszVerIndProgID - Version independent ProgID
//
//   NOTE: The function deletes the HKCR\CLSID\{<CLSID>} key and the 
//   HKCR\<ProgID> key in the registry.
//
HRESULT UnregisterInprocServer(const CLSID& clsid, 
                               PCWSTR pszProgID, 
                               PCWSTR pszVerIndProgID);


//
//   FUNCTION: RegisterTypeLib
//
//   PURPOSE: Register the type library.
//
//   PARAMETERS:
//   * pszTypeLib - The type library file.
//
//   NOTE: The function creates the HKCR\TypeLib\{<LIBID>} key and the 
//   HKCR\Interface\{<IID>} key in the registry.
// 
//   HKCR
//   {
//      NoRemove TypeLib
//      {
//          ForceRemove {<LIBID>}
//          {
//              1.0
//              {
//                  0
//                  {
//                      win32 = s '%MODULE%'
//                  }
//                  FLAGS = 0
//                  HELPDIR = s '%MODULE DIR%'
//              }
//          }
//      }
//      NoRemove Interface
//      {
//          ForceRemove {<IID>} = s '<Interface Name>'
//          {
//              ProxyStubClsid = s '<ProgID>'
//              ProxyStubClsid32 = s '<VersionIndependentProgID>'
//              TypeLib = s '{<LIBID>}'
//              {
//                  val Version = s '<TypeLib Version>'
//              }
//          }
//      }
//   }
//
HRESULT RegisterTypeLib(PCWSTR pszTypeLib);


//
//   FUNCTION: UnregisterTypeLib
//
//   PURPOSE: Unregister the type library.
//
//   PARAMETERS:
//   * pszTypeLib - The type library file.
//
//   NOTE: The function deletes the HKCR\TypeLib\{<LIBID>} key and the 
//   HKCR\Interface\{<IID>} key in the registry.
//
HRESULT UnregisterTypeLib(PCWSTR pszTypeLib);